package lib.bone.admin.controller.research;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.Validator;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lib.bone.access.module.dict.entity.NepuAwardDict;
import lib.bone.admin.anno.FormLock;
import lib.bone.access.constant.AwardTypeConst;
import lib.bone.access.constant.ResearchTypeConst;
import lib.bone.nepudata.domain.dto.award.NepuAwardAddDTO;
import lib.bone.nepudata.domain.dto.award.NepuAwardQueryDTO;
import lib.bone.nepudata.domain.dto.award.NepuAwardUpdateDTO;
import lib.bone.ext.draft.NepuDraft;
import lib.bone.ext.draft.NepuDraftService;
import lib.bone.access.config.cycle.NepuCycleService;
import lib.bone.access.module.dict.DictServiceCtl;
import lib.bone.access.module.oss.NepuResearchFileService;
import lib.bone.nepudata.domain.entity.NepuAward;
import lib.bone.nepudata.service.ResearchServiceCtl;
import lib.bone.nepudata.service.impl.NepuAwardServiceImpl;
import lib.bone.admin.anno.WebLog;
import lib.bone.admin.constant.MethodTypeConst;
import lib.bone.admin.domain.dto.FileUpdateDTO;
import lib.bone.common.constant.ResponseCodeConst;
import lib.bone.common.core.domain.ResponseDTO;
import lib.bone.common.utils.JsonUtil;
import lib.bone.flow.domain.dto.FlowParam;
import lib.bone.flow.service.FlowTaskService;
import lib.bone.flow.service.FlowWorkCtl;
import lib.bone.flow.service.FlowWorkService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

/**
 * @Author : kindear
 * @Date : 2022-1-10
 */

/**
 * cg
 */
@Slf4j
@RestController
@RequestMapping("nepu")
@Api(tags = "教学科研获奖")
public class NepuAwardController {

    @Autowired
    NepuDraftService draftService;

    @Autowired
    ResearchServiceCtl researchServiceCtl;

    @Autowired
    NepuAwardServiceImpl nepuAwardService;

    @Autowired
    DictServiceCtl dictServiceCtl;

    @Autowired
    NepuResearchFileService nepuResearchFileService;

    @Autowired
    FlowWorkCtl flowWorkCtl;

    @Autowired
    FlowWorkService workService;

    @Autowired
    NepuCycleService cycleService;

    @Autowired
    FlowTaskService flowTaskService;

    /**
     * 表单校验
     * @param dto
     * @return
     */
    public String formValid(NepuAwardAddDTO dto){
        // 表单重复性校验
        String errMsg = "";
        Long operator = StpUtil.getLoginIdAsLong();
        Long leaderId = dto.getLeaderId();
        if (!leaderId.equals(operator)){
            errMsg = "您不是负责人，无法申报该项目";
            return errMsg;
        }
//        Optional<NepuAward> awardOp = nepuAwardService.findByAwardNameAndLeader(
//                dto.getAwardName(),
//                dto.getLeader()
//        );


//        if (awardOp.isPresent()) {
//            NepuAward award = awardOp.get();
//            if (award.getLeader() == )
//            errMsg = "存在重复记录";
//            return errMsg;
//        }
        List<Long> userIds = dto.getUserIdList();
        if (userIds.contains(dto.getLeaderId())){
            errMsg = "参与人员中不需添加负责人";
            return errMsg;
        }
        return errMsg;
    }

    @PostMapping("awards/storage")
    @FormLock(lockKey = "AWARD_STORE",needLogin = true)
    @ApiOperation(value = "暂存记录",notes = "")
    public ResponseDTO<Object> setStorage(@RequestBody  NepuAwardAddDTO dto){
        Long userId = StpUtil.getLoginIdAsLong();
        Optional<Object> dictOp = dictServiceCtl.getById(dto.getAwardDictId(),ResearchTypeConst.AWARD);
        if (!dictOp.isPresent()){
            return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND);
        }
        NepuAwardDict dict = (NepuAwardDict) dictOp.get();
        String awardType = dict.getAwardType();
        NepuDraft draft = new NepuDraft();
        draft.setFormId(ResearchTypeConst.AWARD+awardType);
        draft.setStatus(1);
        draft.setUserId(userId);
        draft.setFormJsonStr(JsonUtil.obj2String(dto));
        return ResponseDTO.succData(draftService.saveOne(draft));
    }

    @GetMapping("awards/storage")
    @ApiOperation(value = "获取最新暂存")
    public ResponseDTO<Object> getStorage(@RequestParam("awardType") String awardType){
        //log.info(awardType);
        Long userId = StpUtil.getLoginIdAsLong();
        Optional<NepuDraft> draftOp = draftService.getLastDraft(userId,ResearchTypeConst.AWARD+awardType);
        if (!draftOp.isPresent()) return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND);
        NepuDraft draft = draftOp.get();
        return ResponseDTO.succData(JsonUtil.string2Obj(draft.getFormJsonStr(),NepuAwardAddDTO.class));
    }

    @GetMapping("awards/storage/all")
    @ApiOperation(value = "获取全部暂存")
    public ResponseDTO<Object> getAllStorage(@RequestParam("awardType") String awardType){
        Long userId = StpUtil.getLoginIdAsLong();
        List<NepuDraft> drafts = draftService.getFormAllDrafts(userId,ResearchTypeConst.AWARD+awardType);
        return ResponseDTO.succData(drafts);
    }


    @WebLog(module = "nepu-access")
    @PostMapping("awards")
    @FormLock(lockKey = "AWARD_FORM",needLogin = true)
    @ApiOperation(value = "新建记录",notes = "")
    public ResponseDTO<Object> saveOne(@RequestBody @Validated NepuAwardAddDTO nepuAwardAddDTO){
//        //重复性校验 -- 根据获奖题目与负责人cg
//        Optional<NepuAward> nepuAwardOp = nepuAwardService.findByAwardNameAndLeader(nepuAwardAddDTO.getAwardName(),nepuAwardAddDTO.getLeader());
//        if (nepuAwardOp.isPresent()){
//            return ResponseDTO.wrap(ResponseCodeConst.ERROR_PARAM,"重复的获奖名称与负责人！");
//        }
        // 1. 获取当前登录用户ID -- 自动拦截未登录用户
//        String operator = StpUtil.getLoginIdAsString();
//        String leaderId = nepuAwardAddDTO.getLeaderId().toString();
//        log.info("负责人ID:{},登录用户ID:{}",leaderId,operator);
//        if (!leaderId.equals(operator)){
//            return ResponseDTO.wrap(ResponseCodeConst.FORBIDDEN,"您不是负责人，无法申报该项目");
//        }
//        List<Long> userIds = nepuAwardAddDTO.getUserIdList();
//        if (userIds.contains(nepuAwardAddDTO.getLeaderId())){
//            return ResponseDTO.wrap(ResponseCodeConst.FORBIDDEN,"参与人员不需加入负责人");
//        }
        // 2. 获取当前时间所在周期ID -- 自动拦截不在时间段内的提交
        // 1. 获取操作人员ID
        String operator = StpUtil.getLoginIdAsString();
        //查询是否存在被驳回的重复提交
        String errMsg = formValid(nepuAwardAddDTO);
        if (!Validator.isEmpty(errMsg)){
            return ResponseDTO.wrap(ResponseCodeConst.ERROR_PARAM,errMsg);
        }
        //String cycleId = cycleService.getNowCycleId();
        String cycleId = cycleService.getNowResearchCycleId();
        // 3. 获取词典信息
        Optional<Object> dictOp = dictServiceCtl.getById(nepuAwardAddDTO.getAwardDictId(),ResearchTypeConst.AWARD);
        if (!dictOp.isPresent()){
            return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND);
        }
        NepuAwardDict dict = (NepuAwardDict) dictOp.get();
        // 4. 写入记录 并赋值最大工作量
        NepuAward saveEntity = new NepuAward();
        BeanUtil.copyProperties(nepuAwardAddDTO,saveEntity,CopyOptions.create().setIgnoreError(true).setIgnoreNullValue(true));
        saveEntity.setWorkload(dict.getWorkloadMax());
        saveEntity.setCycleId(cycleId);

        NepuAward award = (NepuAward) researchServiceCtl.saveOne(saveEntity);
        // 5. 写入绑定文件信息 -- 修改为异步任务
        List<String> fileIds = nepuAwardAddDTO.getFileIds();
        nepuResearchFileService.batchBindFile(ResearchTypeConst.AWARD,award.getId(),fileIds);
        // 6. 构建流程参数
        FlowParam flowParam = new FlowParam(ResearchTypeConst.AWARD,award.getId(),award.getAwardName(),operator,null);
//        flowParam.setServiceType(ResearchTypeConst.AWARD);
//        flowParam.setServiceId(award.getId());
//        flowParam.setServiceName(award.getAwardName());
//        flowParam.setOperator(operator);
        // 7. 启动流程实例 -- 修改为异步任务
        String awardType = dict.getAwardType();
        //log.info(nepuAwardAddDTO.toString());
        if (awardType.equals(AwardTypeConst.RESEARCH)) {
            switch (nepuAwardAddDTO.getDeptName()) {
                case "科研处": {
                    flowWorkCtl.startProcess("award-check-01", operator, flowParam);
                    break;
                }
                case "学术理论部": {
                    flowWorkCtl.startProcess("award-check-06", operator, flowParam);
                    break;
                }
                case "学科建设处": {
                    flowWorkCtl.startProcess("award-check-07", operator, flowParam);
                    break;
                }
            }
        }else if (awardType.equals(AwardTypeConst.TEACH)){
            switch (nepuAwardAddDTO.getDeptName()){
                case "教务处": {
                    flowWorkCtl.startProcess("award-check-02", operator, flowParam);
                    break;
                }
                case "高等教育研究中心":{
                    flowWorkCtl.startProcess("award-check-03", operator, flowParam);
                    break;
                }
                case "研究生部":{
                    flowWorkCtl.startProcess("award-check-04", operator, flowParam);
                    break;
                }
                case "秦皇岛分校":{
                    flowWorkCtl.startProcess("award-check-05", operator, flowParam);
                    break;
                }

            }
        }


        return ResponseDTO.succData(award);
    }

    @WebLog(module = "nepu-access",operate = MethodTypeConst.DELETE)
    @DeleteMapping("awards/{id}")
    @ApiOperation(value = "删除单条记录",notes = "传入ID")
    public ResponseDTO<Object> deleteOne(@PathVariable("id") String id){
        return researchServiceCtl.deleteById(id,ResearchTypeConst.AWARD);
    }

    @GetMapping("awards/{id}")
    @ApiOperation(value = "查询单条记录",notes = "传入ID")
    public ResponseDTO<Object> getOne(@PathVariable("id") String id){
        Optional<Object> entityOp = researchServiceCtl.getById(id,ResearchTypeConst.AWARD);
        return entityOp.map(ResponseDTO::succData).orElseGet(() -> ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND));
    }

    @GetMapping("awards/{id}/files")
    @ApiOperation(value = "查询关联附件",notes = "")
    public ResponseDTO<Object> queryBindFiles(@PathVariable("id") String id){
        return ResponseDTO.succData(
                nepuResearchFileService.getList(ResearchTypeConst.AWARD, id)
        );

    }


    /** 更新单条记录 **/
    @WebLog(module = "nepu-access",operate = MethodTypeConst.UPDATE)
    @PutMapping("awards")
    @ApiOperation(value = "更新单条记录",notes = "")
    public ResponseDTO<Object> updateOne(@RequestBody @Validated NepuAwardUpdateDTO nepuAwardUpdateDTO){
        Optional<Object> awardOp = researchServiceCtl.getById(nepuAwardUpdateDTO.getId(),ResearchTypeConst.AWARD);
        if (!awardOp.isPresent()){
            return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND);
        }
        NepuAward award = (NepuAward) awardOp.get();
        BeanUtil.copyProperties(nepuAwardUpdateDTO,award,CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        return ResponseDTO.succData(researchServiceCtl.updateOne(award,ResearchTypeConst.AWARD));
    }

    @WebLog(module = "nepu-access",operate = MethodTypeConst.UPDATE)
    @PutMapping("awards/files")
    @ApiOperation(value = "更新附件信息",notes = "")
    public ResponseDTO<Object> updateFiles(@RequestBody @Validated FileUpdateDTO dto){
        Long userId = StpUtil.getLoginIdAsLong();
        Optional<Object> awardOp = researchServiceCtl.getById(dto.getMapperId(),ResearchTypeConst.AWARD);
        if (!awardOp.isPresent()){
            return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND);
        }
        NepuAward award = (NepuAward) awardOp.get();
        if (!userId.equals(award.getLeaderId())){
            return ResponseDTO.wrap(ResponseCodeConst.FORBIDDEN,"非负责人无法修改");
        }
        // 清理之前的附件信息
        nepuResearchFileService.deleteEntityLink(award.getId());
        // 写入新的附件信息
        List<String> fileIds = dto.getFileIds();
        nepuResearchFileService.batchBindFile(ResearchTypeConst.AWARD,award.getId(),fileIds);
        // 返回操作信息
        return ResponseDTO.succMsg("更新成功");
    }

    @WebLog(module = "nepu-access",operate = MethodTypeConst.SELECT,allowMask = 1)
    @GetMapping("awards")
    @ApiOperation(value = "查询全部",notes = "")
    public ResponseDTO<Object> getAll(NepuAwardQueryDTO nepuAwardQueryDTO){
        Sort sort;
        if(nepuAwardQueryDTO.getOrder().equalsIgnoreCase("DESC")){
            sort = Sort.by(Sort.Direction.DESC, nepuAwardQueryDTO.getSortBy());
        }else {
            sort = Sort.by(Sort.Direction.ASC, nepuAwardQueryDTO.getSortBy());
        }

        // tips : 页码对应 - 1
        Pageable pageable = PageRequest.of(nepuAwardQueryDTO.getPageNum() - 1 , nepuAwardQueryDTO.getPageSize(), sort);

        NepuAward nepuAward = new NepuAward();
        BeanUtil.copyProperties(nepuAwardQueryDTO,nepuAward, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        Example<NepuAward> example = Example.of(nepuAward);
        return ResponseDTO.succData(researchServiceCtl.getAll(pageable,example,ResearchTypeConst.AWARD));
    }

    @WebLog(module = "nepu-access",operate = MethodTypeConst.UPDATE)
    @PutMapping("awards/{id}/workload")
    @ApiOperation(value = "修改记录工作量")
    public ResponseDTO<Object> updateWorkload(@PathVariable("id") String id,@RequestParam("workload") Double workload){
        Optional<Object> entityOp = researchServiceCtl.getById(id,ResearchTypeConst.AWARD);
        if (!entityOp.isPresent()){
            return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND,"未找到对应课题记录");
        }
        NepuAward award = (NepuAward) entityOp.get();
        String dictId = award.getAwardDictId();
        Optional<Object> dictOp = dictServiceCtl.getById(dictId,ResearchTypeConst.AWARD);
        if (!dictOp.isPresent()){
            return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND,"未找到课题关联词典记录");
        }
        NepuAwardDict dict = (NepuAwardDict) dictOp.get();
        if (workload > dict.getWorkloadMax() || workload < dict.getWorkloadMin()){
            return ResponseDTO.wrap(ResponseCodeConst.ERROR_PARAM,"工作量范围错误");
        }
        award.setWorkload(workload);
        // 写入记录
        return ResponseDTO.succData(researchServiceCtl.updateOne(award,ResearchTypeConst.AWARD));
    }

}
